package read;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class POIExcelUtil {
	/**
	 * 使用POI读取Excel，并且将数据封装到List<Map>的结构中，Excel的一行放一个map中去，一个sheet页放到一个List中去
	 * 此工具类仅支持2007版之后的Excel,即扩展名为.xlsx
	 * 
	 * @throws IOException
	 */
	public static List<Map> read_Excel(String src_xlsxPath, int cellCount) throws IOException {
		/**
		 * src_xlsxPath代表要读取的Excel的全路径 cellCount代表Excel的最大列数
		 */
		List<Map> list = new ArrayList<Map>();
		File file = new File(src_xlsxPath);
		if (!file.exists()) {
			throw new IOException("文件名为" + file.getName() + "的Excel文件不存在！");
		}
		XSSFWorkbook wb = null;
		try {
			FileInputStream fis = new FileInputStream(file);
			// 去读取Excel
			wb = new XSSFWorkbook(fis);
			// 循环Excel的每一个sheet页
			int numberOfSheets = wb.getNumberOfSheets();
			for (int i = 0; i < numberOfSheets; i++) {
				// 获取每一个sheet页
				XSSFSheet sheet = wb.getSheetAt(i);
				// 循环每一行
				for (Row row : sheet) {
					Map map = new HashMap<String, String>();
					// 获取行号
					int rowNum = row.getRowNum();
					// 循环每一行中的每一个单元格
					int columnNum = 1;
					for (int j = 0; j < row.getLastCellNum(); j++) {
						// 获取每个单元格的值
						String cellValue = String.valueOf(row.getCell(j));
						cellValue = cellValue.replaceAll("null", "");
						// 用每个单元格的行号和列号拼成的字符串作为存储每个单元格值得key
						String key = String.valueOf(rowNum + 1) + String.valueOf(columnNum);
						// 把每个单元格的内容存储到一个map中去
						map.put(key, cellValue);
						columnNum++;
						System.out.println(key+cellValue);
					}
					// 把每一个sheet存储到一个List集合中去
					list.add(map);
				}
			}
			// 关闭流资源
			fis.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * 使用POI技术把指定格式的数据存储到Excel中去
	 */
	public static void write_Excel(String dist_xlsxPath, @SuppressWarnings("rawtypes") List<Map> list,
			String sheet_name) {
		/**
		 * list表示所要存储的数据 sheet_name表示所要存储sheet页的名称
		 * dist_xlsxPath表示把所给的数据存储到的Excel的全路径名
		 */
		Workbook workbook = null;
		try {
			workbook = new XSSFWorkbook();
		} catch (Exception e) {
			System.out.println("创建Excel失败!!!");
			e.printStackTrace();
		}
		if (workbook != null) {
			// 创建所需要的sheet页
			Sheet sheet = workbook.createSheet(sheet_name);
			// 获取sheet页的首行对象
			Row row0 = sheet.createRow(0);
			// 获取所要存储数据的总行数
			int totalRow = list.size();
			@SuppressWarnings("rawtypes")
			// 获取首行数据，即Excel每一列的列名
			Map map = list.get(0);
			// 获取总列数
			int totalColumn = map.size();
			// 循环添加第一行的标题
			for (int i = 0; i < totalColumn; i++) {
				Cell cell = row0.createCell(i, Cell.CELL_TYPE_STRING);
				String value = (String) map.get(1 + String.valueOf(i + 1));
				cell.setCellValue(value);
				sheet.autoSizeColumn(i);// 自动调整宽度
				if (sheet.getColumnWidth(i) < 2048) {
					sheet.setColumnWidth(i, 2048);
				}
			}
			// 循环添加第一行标题下面的具体内容
			for (int rowNum = 1; rowNum < totalRow; rowNum++) {
				Map maplist = list.get(rowNum);
				Row row = sheet.createRow(rowNum);
				for (int i = 0; i < totalColumn; i++) {
					Cell cell = row.createCell(i, Cell.CELL_TYPE_STRING);
					String value = (String) maplist.get(rowNum + 1 + String.valueOf(i + 1));
					cell.setCellValue(value);
					sheet.autoSizeColumn(i);// 自动调整宽度
					if (sheet.getColumnWidth(i) < 2048) {
						sheet.setColumnWidth(i, 2048);
					}
				}
			}
			try {
				// 用流生成Excel文件
				FileOutputStream outputStream = new FileOutputStream(dist_xlsxPath);
				workbook.write(outputStream);
				outputStream.flush();
				// 关闭流资源
				outputStream.close();
			} catch (Exception e) {
				System.out.println("写入Excel失败!!!");
				e.printStackTrace();
			}
		}
	}

}
